package com.sxhuayuan.parking.controller.member;

import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.alibaba.fastjson.JSON;
import com.sxhuayuan.parking.compenent.Message;
import com.sxhuayuan.parking.compenent.domain.Setting;
import com.sxhuayuan.parking.compenent.web.RespMessage;
import com.sxhuayuan.parking.config.PayStatus;
import com.sxhuayuan.parking.dto.ParkFeeCacheBean;
import com.sxhuayuan.parking.dto.QueryFeeDTO;
import com.sxhuayuan.parking.entity.Member;
import com.sxhuayuan.parking.entity.OriginalParkingInfo;
import com.sxhuayuan.parking.entity.ParkChannel;
import com.sxhuayuan.parking.entity.ParkingIn;
import com.sxhuayuan.parking.entity.ParkingLot;
import com.sxhuayuan.parking.exception.MyException;
import com.sxhuayuan.parking.plugin.parking.ParkingPlugin;
import com.sxhuayuan.parking.plugin.parking.result.BaseResultWrap;
import com.sxhuayuan.parking.plugin.parking.result.QueryParkingFeeResultWrap;
import com.sxhuayuan.parking.plugin.parking.tingzhihui.TingzhihuiParkingPlugin;
import com.sxhuayuan.parking.plugin.payment.WxPayPlugin;
import com.sxhuayuan.parking.service.MemberCarPlateService;
import com.sxhuayuan.parking.service.MemberService;
import com.sxhuayuan.parking.service.MonthCardOrderService;
import com.sxhuayuan.parking.service.OrderService;
import com.sxhuayuan.parking.service.OriginalParkingInfoService;
import com.sxhuayuan.parking.service.ParkChannelService;
import com.sxhuayuan.parking.service.ParkFeeCacheService;
import com.sxhuayuan.parking.service.ParkingInService;
import com.sxhuayuan.parking.service.ParkingLotService;
import com.sxhuayuan.parking.service.PluginService;
import com.sxhuayuan.parking.utils.DateUtils;
import com.sxhuayuan.parking.utils.DeviceUtil;
import com.sxhuayuan.parking.utils.SettingUtils;
import com.sxhuayuan.parking.utils.SnowFlake;
import com.sxhuayuan.parking.utils.SpringUtils;

/**
 * 车主扫码支付入口,包括公众号网页和小程序
 */
@Controller
@RequestMapping("/member/park")
public class ParkingController extends BaseController {

	@Autowired
	MemberService memberService;
	@Autowired
	MemberCarPlateService memberCarPlateService;
	@Autowired
	OrderService orderService;
	@Autowired
	WxPayPlugin wxpayPlugin;
	@Autowired
	ParkingLotService parkingLotService;
	@Autowired
	ParkingInService parkingInService;
	@Autowired
	ParkChannelService exitService;
	@Autowired
	OriginalParkingInfoService originalParkingInfoService;
	@Autowired
	MonthCardOrderService monthCardOrderService;
	@Autowired
	ParkFeeCacheService parkFeeCacheService;
	@Autowired
	PluginService pluginService;
	@Resource(name = "orderNoFactory")
	SnowFlake orderNoFactory;

	Logger log = LoggerFactory.getLogger(getClass());

	/**
	 * 2019-5-16后改为不同的链接，这个链接不再在新车场中使用<br>
	 * 车主扫描出口二维码，lv=1时自动获取车牌
	 * 
	 * @param redirectAttributes
	 * @param request
	 * @param model
	 * @param exit
	 * @param lv
	 *            leaving 是否正在出口,是则查询车牌
	 * @return
	 */
	@Deprecated
	@RequestMapping(value = "/qr/{exit}", method = RequestMethod.GET)
	public String qrcode(RedirectAttributes redirectAttributes, HttpServletRequest request, Model model, @PathVariable("exit") String exit, String lv) {
		if (exit == null || exitService.findBySn(exit) == null) {
			addErrorMessage(Message.PARK_CHANNEL_NOT_EXISTS);
			return ERROR_VIEW;
		}
		// 跳转到新地址
		if (StringUtils.isBlank(lv)) {
			ParkingLot lot = exitService.findBySn(exit).getParkingLot();
			return "forward:/member/park/pre/" + lot.getSn();
		} else {
			return "forward:/member/park/pay/" + exit;
		}
	}

	/**
	 * 车主扫描出口支付二维码（自动获取车牌）
	 * 
	 * @param redirectAttributes
	 * @param request
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/pay/{exit}", method = RequestMethod.GET)
	public String pay(RedirectAttributes redirectAttributes, HttpServletRequest request, Model model, @PathVariable("exit") String exit) {
		if (exit == null || exitService.findBySn(exit) == null) {
			addErrorMessage(Message.PARK_CHANNEL_NOT_EXISTS);
			return ERROR_VIEW;
		}
		return "redirect:/member/park/payment";
	}

	/**
	 * 车主扫描预支付二维码
	 * 
	 * @param redirectAttributes
	 * @param request
	 * @param model
	 * @param lotSn
	 * @return
	 */
	@RequestMapping(value = "/pre/{lotSn}", method = RequestMethod.GET)
	public String prePay(RedirectAttributes redirectAttributes, HttpServletRequest request, Model model, @PathVariable("lotSn") String lotSn) {
		if (lotSn == null || parkingLotService.findBySn(lotSn) == null) {
			addErrorMessage(Message.PARKING_LOT_NOT_EXISTS);
			return ERROR_VIEW;
		}
		Member member = memberService.getCurrent();
		/** 用户存在 但没有绑定车牌号 跳转到绑定车牌号界面 */
		Long carplateCount = memberCarPlateService.findCount(member.getId());
		if (carplateCount == 0) {
			return "redirect:/member/carplate/bind";
		}
		return "redirect:/member/park/payment";
	}

	/**
	 * 缴费页面
	 */
	@RequestMapping(value = "/payment", method = RequestMethod.GET)
	public String payment(HttpServletRequest request, Model model) {
		String lotSn = getLotSnFromSession();
		ParkingLot lot = parkingLotService.findBySn(lotSn);
		if (lot == null) {
			return ERROR_VIEW;
		}
		String userAgent = request.getHeader("User-Agent");
		log.debug("客户端:{}", userAgent);
		if (DeviceUtil.isFromWeixin(userAgent) && !lot.getIsWeixinEnable()) {
			addErrorMessage(Message.ORDER_WEIXIN_NOT_ENABLE);
			return ERROR_VIEW;
		}
		if (DeviceUtil.isFromAlipay(userAgent) && !lot.getIsAlipayEnable()) {
			addErrorMessage(Message.ORDER_ALIPAY_NOT_ENABLE);
			return ERROR_VIEW;
		}
		try {
			// 是否扫的出口码
			String exitSn = getExitSnFromSession();
			if (StringUtils.isNotBlank(exitSn)) {
				// 判断是否是测试车场
				if (lot.getSn().equals(SettingUtils.get().getTestParkingLotSn())) {
					QueryParkingFeeResultWrap wrap = getTestQueryParkingFeeResultWrap(lot, exitService.findBySn(exitSn), SettingUtils.get().getTestCarPlate());
					model.addAttribute("parkingFeeResult", JSON.toJSONString(wrap));
				} else {
					ParkingPlugin plugin = pluginService.getParkingPlugin(lot.getPluginId());
					QueryParkingFeeResultWrap parkingFeeResult = plugin.queryLeavingCarParkingLotOrder(lot, exitSn, memberService.getCurrent());
					model.addAttribute("parkingFeeResult", JSON.toJSONString(parkingFeeResult));
				}
			}
		} catch (MyException e) {
			String message = SpringUtils.getMessage(e.getMessage());
			model.addAttribute("parkingFeeResult", JSON.toJSONString(new BaseResultWrap(false, message)));
		}
		model.addAttribute("lot", lot);
		if (StringUtils.isNotBlank(getExitSnFromSession())) {
			model.addAttribute("exitName", exitService.findBySn(getExitSnFromSession()).getName());
		}
		return "payment/payment";
	}

	/**
	 * 查询停车计费信息
	 * 
	 * @param queryFeeData
	 * @param request
	 * @return
	 */
	@RequestMapping("/queryfee")
	@ResponseBody
	public RespMessage queryFee(@Validated @RequestBody QueryFeeDTO queryFeeData, HttpServletRequest request) {
		ParkingLot lot = parkingLotService.findBySn(getLotSnFromSession());
		// 如果是测试车场的话 返回自定义虚拟订单信息
		if (lot.getSn().equals(SettingUtils.get().getTestParkingLotSn())) {
			ParkChannel exit = exitService.findBySn(getExitSnFromSession());
			QueryParkingFeeResultWrap wrap = getTestQueryParkingFeeResultWrap(lot, exit, queryFeeData.getCarPlate());
			if (wrap.getIsSuccess()) {
				return RespMessage.builder().success().setDatas(wrap).build();
			} else {
				return RespMessage.error(wrap.getMsg());
			}
		}
		ParkingPlugin plugin = pluginService.getParkingPlugin(lot.getPluginId());
		QueryParkingFeeResultWrap resultWrap = plugin.queryParkingFee(lot, queryFeeData.getCarPlate());
		if (resultWrap.getIsSuccess()) {
			return RespMessage.builder().success().setDatas(resultWrap).build();
		}
		return RespMessage.builder().error().setErr(resultWrap.getMsg()).build();
	}

	/** 测试通道虚拟订单 */
	private QueryParkingFeeResultWrap getTestQueryParkingFeeResultWrap(ParkingLot lot, ParkChannel exit, String carPlate) {
		QueryParkingFeeResultWrap rs = new QueryParkingFeeResultWrap();
		rs.setTime(new Date());
		rs.setIsSuccess(true);
		Setting setting = SettingUtils.get();
		if (carPlate.equals(setting.getTestCarPlate())) {
			Date inTime = DateUtils.add(new Date(), Calendar.MINUTE, -30);
			ParkingIn in = parkingInService.enter(lot, carPlate, inTime, null, lot.getFreeMinutes(), null);
			rs.setUniqueId(String.valueOf(in.getUniqueId()));
			String lotOrderNo = RandomStringUtils.randomNumeric(16);

			// Order order = orderService.create(in, lotOrderNo, inTime, new Date(),
			// exit.getId(), new BigDecimal(0.01f), null, lot.getPluginId(), null, null,
			// Order.Method.exit, "", "测试");
			ParkFeeCacheBean parkFee = new ParkFeeCacheBean();
			parkFee.setLotOrderNo(lotOrderNo);
			parkFee.setDiscountFee(null);
			parkFee.setEndTime(new Date());
			parkFee.setExitDevice(exit.getDeviceId());
			parkFee.setParkPluginId(TingzhihuiParkingPlugin.ID);
			parkFee.setTotalFee(0.01f);
			parkFee.setUniqueId(in.getUniqueId());
			parkFeeCacheService.put(parkFee);

			// Order order = orderService.create(in, null, memberService.getCurrent(), null,
			// null, Order.Method.exit, "", "测试");
			rs.setCardNo("111111111111");
			rs.setCarPlate(carPlate);
			float floatPaymentMoney = setting.getFloatPaymentMoney();
			// 总计
			rs.setCalcFee(floatPaymentMoney);
			// 实收=总计-优惠
			rs.setFee(floatPaymentMoney);
			rs.setCalcStartTime(DateUtils.format(inTime));
			rs.setEntertime(DateUtils.format(inTime));
			rs.setCalcEndTime(DateUtils.format(new Date()));
			rs.setExtraMchid(SettingUtils.get().getTestParkingLotSn());
			rs.setParktimeMinute(30);
			rs.setExtraPluginId(lot.getPluginId());
			rs.setRules("测试车场订单 统计" + floatPaymentMoney + "元");
		} else {
			rs.setIsSuccess(false);
			rs.setMsg("未找到入场记录");
		}
		return rs;
	}

	/**
	 * 测试通道 创建并保存原始订单
	 * 
	 * @param wrap
	 *            订单信息
	 */
	private void creatOriginalOrder(QueryParkingFeeResultWrap wrap) {
		OriginalParkingInfo rs = new OriginalParkingInfo();
		rs.setAmount(new BigDecimal(wrap.getFee()));
		rs.setCalcstarttime(wrap.getCalcStartTime());
		rs.setCalcendtime(wrap.getCalcEndTime());
		rs.setCardInId("123456");
		rs.setCarNo(wrap.getCarPlate());
		rs.setCardNo(wrap.getCardNo());
		rs.setChargeSeqNo(wrap.getNo());
		rs.setCredentialtype("车牌");
		rs.setDiscountDetail("{}");
		rs.setEntertime(wrap.getEntertime());
		rs.setFeeDetail(wrap.getRules());
		rs.setLotOrderNo(wrap.getLotOrderNo());
		rs.setParkcost(new BigDecimal(wrap.getFee()));
		rs.setParkingLot(parkingLotService.findBySn(SettingUtils.get().getTestParkingLotSn()));
		rs.setParkingLotName(rs.getParkingLot().getName());
		rs.setParkposi(rs.getParkingLot().getAddress());
		rs.setPriceRule(wrap.getRules());
		rs.setParktime(wrap.getParktimeMinute().longValue());
		rs.setTotalDiscount(BigDecimal.ZERO);
		rs.setPayStatus(PayStatus.notpay);
		originalParkingInfoService.save(rs);
		log.debug("测试车场订单保存成功...");
	}

}
